﻿#include "ConcurrentAlloc.h"
#include <iostream>
#include <vector>
#include <thread>
#include <atomic>
#include <cstdio>
#include <chrono>
#include <windows.h>  // 用于SetConsoleOutputCP

using namespace std;
using namespace chrono;

inline size_t to_ms(const high_resolution_clock::duration& dur) {
    return duration_cast<milliseconds>(dur).count();
}

void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds) {
    vector<thread> vthread(nworks);
    atomic<size_t> malloc_total(0);
    atomic<size_t> free_total(0);

    for (size_t k = 0; k < nworks; ++k) {
        vthread[k] = thread([&]() {
            vector<void*> allocations;
            allocations.reserve(ntimes);

            for (size_t r = 0; r < rounds; ++r) {
                auto start = high_resolution_clock::now();
                for (size_t i = 0; i < ntimes; ++i) {
                    //allocations.push_back(malloc(16));
                    allocations.push_back(malloc((16 + i) % 8192 + 1));
                }
                auto end = high_resolution_clock::now();
                malloc_total += to_ms(end - start);

                start = high_resolution_clock::now();
                for (void* ptr : allocations) {
                    free(ptr);
                }
                end = high_resolution_clock::now();
                free_total += to_ms(end - start);

                allocations.clear();
            }
            });
    }

    for (auto& t : vthread) {
        if (t.joinable()) t.join();
    }

    size_t malloc_time = malloc_total;
    size_t free_time = free_total;
    size_t total_ops = nworks * rounds * ntimes;

    printf("标准malloc/free基准测试:\n");
    printf("  线程数: %zu, 轮次: %zu, 每轮操作数: %zu\n", nworks, rounds, ntimes);
    printf("  malloc总耗时: %zu ms, 平均每次: %.3f us\n",
        malloc_time, (malloc_time * 1000.0) / total_ops);
    printf("  free总耗时: %zu ms, 平均每次: %.3f us\n",
        free_time, (free_time * 1000.0) / total_ops);
    printf("  总耗时: %zu ms, 总操作数: %zu\n\n",
        malloc_time + free_time, total_ops);
}

void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds) {
    vector<thread> vthread(nworks);
    atomic<size_t> alloc_total(0);
    atomic<size_t> dealloc_total(0);

    for (size_t k = 0; k < nworks; ++k) {
        vthread[k] = thread([&]() {
            vector<void*> allocations;
            allocations.reserve(ntimes);

            for (size_t r = 0; r < rounds; ++r) {
                auto start = high_resolution_clock::now();
                for (size_t i = 0; i < ntimes; ++i) {
                    //allocations.push_back(ConcurrentAlloc(16));
                    allocations.push_back(ConcurrentAlloc((16 + i) % 8192 + 1));
                }
                auto end = high_resolution_clock::now();
                alloc_total += to_ms(end - start);

                start = high_resolution_clock::now();
                for (void* ptr : allocations) {
                    ConcurrentFree(ptr);
                }
                end = high_resolution_clock::now();
                dealloc_total += to_ms(end - start);

                allocations.clear();
            }
            });
    }

    for (auto& t : vthread) {
        if (t.joinable()) t.join();
    }

    size_t alloc_time = alloc_total;
    size_t dealloc_time = dealloc_total;
    size_t total_ops = nworks * rounds * ntimes;

    printf("并发内存分配器基准测试:\n");
    printf("  线程数: %zu, 轮次: %zu, 每轮操作数: %zu\n", nworks, rounds, ntimes);
    printf("  分配总耗时: %zu ms, 平均每次: %.3f us\n",
        alloc_time, (alloc_time * 1000.0) / total_ops);
    printf("  释放总耗时: %zu ms, 平均每次: %.3f us\n",
        dealloc_time, (dealloc_time * 1000.0) / total_ops);
    printf("  总耗时: %zu ms, 总操作数: %zu\n\n",
        alloc_time + dealloc_time, total_ops);
}

int main() {
    // 关键：设置控制台输出编码为UTF-8
    

    const size_t ops_per_round = 10000;
    const size_t thread_count = 4;
    const size_t round_count = 10;

    cout << "===== 内存分配器基准测试 =====" << endl;
    BenchmarkConcurrentMalloc(ops_per_round, thread_count, round_count);
    BenchmarkMalloc(ops_per_round, thread_count, round_count);
    cout << "==============================" << endl;

    return 0;
}